package cn.lg.soar.boot.config;

import cn.lg.soar.common.util.current.UserContext;
import cn.lg.soar.system.api.model.TenantDTO;
import cn.lg.soar.system.api.service.ITenantApi;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;

/**
 * 数据源处理
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
@ConditionalOnProperty(name = "lg.tenant.enable", havingValue = "true")
//@Configuration
public class DataSourceHandler implements WebMvcConfigurer {

    @Autowired
    private ITenantApi tenantApi;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new Interceptor(tenantApi));
    }

    /**
     * 拦截器
     */
    static class Interceptor implements HandlerInterceptor {

        private final ITenantApi tenantApi;

        private final Cache<Integer, String> cache = Caffeine.newBuilder()
                .initialCapacity(128)
                .expireAfterWrite(Duration.ofSeconds(60))
                .build();

        Interceptor(ITenantApi tenantApi) {
            this.tenantApi = tenantApi;
        }

        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            // 查租户
            Integer tenantId = UserContext.getUserOrDef().getCurrentTenantId();
            if (tenantId == null || tenantId == 0) {
                return true;
            }

            // 查租户对应数据源，使用缓存加速（避免每次发网络请求）
            String ds = cache.get(tenantId, key -> {
                TenantDTO tenant = tenantApi.getById(tenantId);
                if (tenant != null) {
                    return tenant.getDataSourceId();
                }
                return "";
            });

            // 切换数据源
            DynamicDataSourceContextHolder.push(ds);
            return true;
        }

    }

}
